﻿// 麻省理工学院许可证
//
// 版权所有 (c) 2023-2025 缄默 联系电话/18521355630 
//
// 特此免费授予获得本软件的任何人以处理本软件的权利，但须遵守以下条件：在所有副本或重要部分的软件中必须包括上述版权声明和本许可声明。
//
// 软件按“原样”提供，不提供任何形式的明示或暗示的保证，包括但不限于对适销性、适用性和非侵权的保证。
// 在任何情况下，作者或版权持有人均不对任何索赔、损害或其他责任负责，无论是因合同、侵权或其他方式引起的，与软件或其使用或其他交易有关。

using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Reflection;

namespace LvcChong
{
    public static class WinFormExtensions
    {
        const float cos30 = 0.866f;
        const float sin30 = 0.5f;
        public static void BindWaterMark(this Control ctrl, string watermark)
        {
            if (ctrl == null || ctrl.IsDisposed)
                return;
            // 绘制水印
            if (ctrl.HaveEventHandler("Paint", "BindWaterMark"))
                return;
            ctrl.Paint += (sender, e) =>
            {
                System.Windows.Forms.Control paintCtrl = sender as System.Windows.Forms.Control;
                var g = e.Graphics;
                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

                // 计算控件位置
                int offsetX = 0;
                int offsetY = 0;
                while (paintCtrl.Parent != null)
                {
                    offsetX += paintCtrl.Location.X;
                    offsetY += paintCtrl.Location.Y;
                    paintCtrl = paintCtrl.Parent;
                }

                // 平移画布到窗体左上角
                g.TranslateTransform(0 - offsetX, 0 - offsetY + 32);

                //逆时针旋转30度
                g.RotateTransform(-30);

                for (int x = 0; x < e.ClipRectangle.Right + 64 + offsetX; x += 128)
                {
                    for (int y = 0; y < e.ClipRectangle.Bottom + 64 + offsetY; y += 128)
                    {
                        // 计算文字起点位置
                        float x1 = cos30 * x - sin30 * y;
                        float y1 = sin30 * x + cos30 * y;

                        //画上文字
                        g.DrawString(watermark, new Font("微软雅黑", 16, FontStyle.Regular),
                            new SolidBrush(Color.FromArgb(50, 100, 100, 100)), x1, y1);
                    }
                }
            };
            // 子控件绑定绘制事件
            foreach (System.Windows.Forms.Control child in ctrl.Controls)
                BindWaterMark(child, watermark);
        }

        public static bool HaveEventHandler(this Control control, string eventName, string methodName)
        {
            //获取Control类定义的所有事件的信息
            PropertyInfo pi = (control.GetType()).GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic);
            //获取Control对象control的事件处理程序列表
            EventHandlerList ehl = (EventHandlerList)pi.GetValue(control, null);

            //获取Control类 eventName 事件的字段信息
            FieldInfo fieldInfo = (typeof(Control)).GetField(string.Format("Event{0}", eventName), BindingFlags.Static | BindingFlags.NonPublic);
            //用获取的 eventName 事件的字段信息，去匹配 control 对象的事件处理程序列表，获取control对象 eventName 事件的委托对象
            //事件使用委托定义的，C#中的委托时多播委托，可以绑定多个事件处理程序，当事件发生时，这些事件处理程序被依次执行
            //因此Delegate对象，有一个GetInvocationList方法，用来获取这个委托已经绑定的所有事件处理程序
            Delegate d = ehl[fieldInfo.GetValue(null)];

            if (d == null)
                return false;

            foreach (Delegate del in d.GetInvocationList())
            {
                string anonymous = string.Format("<{0}>", methodName);
                //判断一下某个事件处理程序是否已经被绑定到 eventName 事件上
                if (del.Method.Name == methodName || del.Method.Name.StartsWith(anonymous))
                {
                    return true;
                }
            }

            return false;
        }

        public static void UpdateUI(this System.Windows.Forms.Control control, MethodInvoker methodInvoker)
        {
            if (control.InvokeRequired)
            {
                try
                {
                    if (!control.Disposing && !control.IsDisposed)
                    {
                        control.Invoke(methodInvoker);
                    }
                }
                catch (ThreadAbortException ex)
                {
                    //NLogHelper.Error(ex, ex.Message);
                }
                catch (ObjectDisposedException ex)
                {
                    //NLogHelper.Error(ex, ex.Message);
                }
                catch (InvalidAsynchronousStateException ex)
                {
                    //NLogHelper.Error(ex, ex.Message);
                }
                catch (ArgumentOutOfRangeException ex)
                {
                    //NLogHelper.Error(ex, ex.Message);
                }
            }
            else
            {
                try
                {
                    methodInvoker();
                }
                catch (ThreadAbortException ex)
                {
                    //NLogHelper.Error(ex, ex.Message);
                }
                catch (ObjectDisposedException ex)
                {
                    //NLogHelper.Error(ex, ex.Message);
                }
                catch (Exception ex)
                {
                    //NLogHelper.Error(ex, ex.Message);
                }
            }
        }
    }
}